import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:path_provider/path_provider.dart';
import 'package:vg_base/src/callback/base_callback.dart';
import 'package:vg_base/src/callback/upload_callback.dart';
import 'package:vg_base/src/http/http_utils.dart';
import 'package:vg_base/src/http/vg_http_response.dart';
import 'package:vg_base/src/http/videocompassplugin.dart';
import 'package:vg_base/vg_base_callback.dart';
import 'package:vg_base/vg_http_lib.dart';
import 'package:vg_base/vg_log_lib.dart';
import 'package:vg_base/vg_string_util_lib.dart';
import 'package:vg_base/vg_time_util_lib.dart';
import 'package:vg_base/vg_upload_callback.dart';
import 'package:vg_base/vg_widget_lib.dart';
import 'package:video_compress/video_compress.dart';
import 'package:video_thumbnail/video_thumbnail.dart';


///OSS上传
///copy Base库
class VgOssUtils {
  /// 上传地址
  static const OSS_UPLOAD_API = "http://zts-et.oss-cn-beijing.aliyuncs.com";

  /// 存到服务器中的图片文件夹名称
  static String FOLDER_IMG = "test";

  /// 存到服务器中的视频文件夹名称
  static String FOLDER_VIDEO = "test";

  /// 存到服务器中的音频文件夹名称
  static String FOLDER_AUDIO = "test";

  static const ACCESSKEY = "MgK6G6T9YcZCQ3watoVWgOA4Hyo1Va";

  static const ACCESSID = "LTAI4FtDmYKP2kKjkesbQhPS";

  ///返回值头
  static const RESULT_URL = "https://etpic.we17.com";
  ///人脸使用，非https
  static const RESULT_URL_HTTP = "http://etpic.we17.com";

  static const BUCKET_NAME = "zts-et";

  ///设置图片文件夹路径
  static void setOssUploadFolderImg(String folderImg) {
    if (StringUtils.isEmpty(folderImg)) {
      return;
    }
    FOLDER_IMG = folderImg;
  }

  ///设置视频文件夹路径
  static void setOssUploadFolderVideo(String folderVideo) {
    if (StringUtils.isEmpty(folderVideo)) {
      return;
    }
    FOLDER_VIDEO = folderVideo;
  }

  ///设置音频文件夹路径
  static void setOssUploadFolderAudio(String folderAudio) {
    if (StringUtils.isEmpty(folderAudio)) {
      return;
    }
    FOLDER_AUDIO = folderAudio;
  }


  /// 上传音频
  static void uploadSingleAudio({File file,
    String path,
    String ext,
    BaseCallback callback,
  }) {
    assert(file != null || !StringUtils.isEmpty(path),
    'file and path cannot be empty at the same time');

    File audioFile;
    if (file == null) {
      audioFile = File(path);
    } else {
      audioFile = file;
    }
    //文件名
    String fileName = _getDefaultAudioFileName(ext);

    Future<VgHttpResponse> future =
    uploadAudio(audioFile, fileName, ext);
    future.then((val) {
      if (val.code == 200) {
        // 上传成功 oss不会返回图片地址 需要自己拼接
        callback
            ?.onSuccess(RESULT_URL + "/" + FOLDER_AUDIO + "/" + fileName);
      } else {
        callback?.onError(val.message);
      }
    }).catchError((onError) {
      callback?.onError("上传单图错误：" + onError?.toString());
    });
  }

  /// 单独上传一个音频的方法
  static Future<VgHttpResponse> uploadAudio(File audioFile, String fileName, String ext) async {
    int length = await audioFile.length();
    LogUtils.i("length：$length");
    //文件名
    FormData data = FormData.fromMap({
      'Filename': fileName,
      'key': FOLDER_AUDIO + "/" + fileName,
      'policy': _getPolicy(),
      'OSSAccessKeyId': ACCESSID,
      'success_action_status': '200', //让服务端返回200，不然，默认会返回204
      'signature': _getSignature(),
      'file': MultipartFile.fromFileSync(audioFile.path, filename: fileName),
      'x-oss-content-type': getXOSSContentType(ext)
    });
    return HttpUtils.post(
        url: OSS_UPLOAD_API, body: data, contentType: "multipart/form-data");
  }

  ///获取contenttype
  static String getXOSSContentType(String ext){
    switch(ext){
      case "ape":
      case "flac":
      case "ogg":
      case "wv":
        return 'application/octet-stream';
      case "mp3":
        return 'audio/mp3';
      case "wav":
        return 'audio/wav';
    }
    return 'application/octet-stream';
  }

  /// 获取默认的图片/视频名称 当前时间+随机数
  static String _getDefaultAudioFileName(String ext) {
    String scope = "0123456789";
    String result = "";
    // 为防止名称重复产生文件覆盖 这里拼接上随机数
    for (int i = 0; i < 4; i++) {
      result = result + scope[Random().nextInt(scope.length)];
    }
    //yyyyMMddhhmmss_xxxx
    String now =
    DateUtil.formatDate(DateTime.now(), format: DataFormats.full_2);
    return "$now$result.${ext}";
  }




  /// 上传单张图片
  static void uploadSingleImage({File file,
    String path,
    String fileName,
    bool isFace,
    bool isNoCompress,
    BaseCallback callback,
    ValueChanged<int> onGetNewFileLength
  }) {
    assert(file != null || !StringUtils.isEmpty(path),
    'file and path cannot be empty at the same time');

    File imageFile;
    if (file == null) {
      imageFile = File(path);
    } else {
      imageFile = file;
    }
    //文件名
    String defaultName = fileName ?? getDefaultFileName(false);

    print("文件大小" + imageFile.lengthSync().toString());
    Future<VgHttpResponse> future = uploadImage(imageFile, defaultName,
        isNoCompress: isNoCompress, onGetNewFileLength: onGetNewFileLength);
    future.then((val) {
      if (val.code == 200) {
        // 上传成功 oss不会返回图片地址 需要自己拼接
        callback?.onSuccess(((isFace ?? false) ? RESULT_URL_HTTP : RESULT_URL) +
            "/" +
            FOLDER_IMG +
            "/" +
            defaultName);
      } else {
        callback?.onError(val.message);
      }
    }).catchError((onError) {
      callback?.onError("上传单图错误：" + onError?.toString());
    });
  }

  /// 上传单个视频
  static void uploadSingleVideo(
      {File file, String path, String fileName, BaseCallback callback}) {
    assert(file != null || !StringUtils.isEmpty(path),
    'file and path cannot be empty at the same time');

    File videoFile;
    if (file == null) {
      videoFile = File(path);
    } else {
      videoFile = file;
    }
    //文件名
    String defaultName = fileName ?? getDefaultFileName(true);

    Future<VgHttpResponse> future = uploadVideo(videoFile, defaultName);
    future.then((val) {
      if (val.code == 200) {
        // 上传成功 oss不会返回图片地址 需要自己拼接
        callback?.onSuccess(
            RESULT_URL + "/" + FOLDER_VIDEO + "/" + defaultName);
      } else {
        callback?.onError(val.message);
      }
    }).catchError((onError) {
      callback?.onError("上传单个视频错误：" + onError?.toString());
    });
  }

  /// 上传多张图片
  static void uploadMulImage({List<File> files,
    List<String> paths,
    bool isNoCompress,
    BaseCallback callback}) {
    assert(files != null || paths != null,
    'files and paths cannot be empty at the same time');
    int startTime = DateTime
        .now()
        .millisecondsSinceEpoch;
    LogUtils.i("上传图片开始");
    // 要上传的文件集合
    List<File> fileList = List<File>();
    // 预先设定好每个要上传的图片名字
    List<String> nameList = List<String>();

    if (files == null) {
      for (String path in paths) {
        fileList.add(File(path));
      }
    } else {
      fileList.addAll(files);
    }
    assert(fileList.length > 0, 'files cannot be empty');

    // 执行多个上传任务的future
    List<Future<VgHttpResponse>> futureList = List<Future<VgHttpResponse>>();
    for (File imageFile in fileList) {
      String name = getDefaultFileName(false);
      nameList.add(name);
      Future<VgHttpResponse> future =
      uploadImage(imageFile, name, isNoCompress: isNoCompress);
      futureList.add(future);
    }
    try {
      Future.wait(futureList).then((values) {
        //values是个数组，分别是每一个任务返回的结果
        // 已上传完的图片url集合
        List<String> urlList = List<String>();
        for (int i = 0; i < values.length; i++) {
          LogUtils.i("${values[i]?.code}");
          if (values[i].code == 200) {
            // 上传成功 oss不会返回图片地址 需要自己拼接
            String imgUrl =
                RESULT_URL + "/" + FOLDER_IMG + "/" + nameList[i];
            urlList.add(imgUrl);
            LogUtils.i(imgUrl);
          } else {
            callback?.onError(values[i]?.message);
            return;
          }
        }
        OssUploadBean uploadBean = OssUploadBean();
        uploadBean.imgList = urlList;
        uploadBean.imgUrls = StringUtils.listToString(urlList);
        callback?.onSuccess(uploadBean);
        LogUtils.i(
            "上传图片结束，耗时:${DateTime
                .now()
                .millisecondsSinceEpoch - startTime}");
      });
    } catch (e) {
      //错误处理
      LogUtils.e(e?.toString());
      callback?.onError("上传多图错误：" + e?.toString());
    }
  }

  /// 上传多个视频
  static Future<void> uploadMulVideo(
      {List<File> files, List<String> paths, BaseCallback callback}) async {
    assert(files != null || paths != null,
    'files and paths cannot be empty at the same time');

    Directory directory = await getTemporaryDirectory();
    String coverFolderPath = directory.path + "/imageTemp";
    // 要上传的文件集合
    List<File> fileList = List<File>();

    if (files == null) {
      for (String path in paths) {
        fileList.add(File(path));
      }
    } else {
      fileList.addAll(files);
    }
    assert(fileList.length > 0, 'files cannot be empty');

    List<File> coverList = List<File>();

    for (File videoFile in fileList) {
      String coverPath = await VideoThumbnail.thumbnailFile(
        video: videoFile.path,
        thumbnailPath: coverFolderPath,
        imageFormat: ImageFormat.JPEG,
        maxWidth: 1920,
        quality: 100,
      );
      coverList.add(File(coverPath));
    }
    // 先上传封面再上传视频
    uploadMulImage(
        files: coverList,
        callback: BaseCallback(onSuccess: (val) {
          // 上传封面成功 开始上传视频
          _upLoadVideoByQueue(val, fileList, callback: callback);
        }, onError: (msg) {
          callback?.onError(msg);
        }));
  }

  static void _upLoadVideoByQueue(OssUploadBean uploadBean, List<File> fileList,
      {BaseCallback callback}) {
    // 预先设定好每个要上传的视频名字
    List<String> nameList = List<String>();

    // 已上传完的视频url集合
    List<String> urlList = List<String>();
    // 执行多个上传任务的future
    List<Future<VgHttpResponse>> futureList = List<Future<VgHttpResponse>>();
    for (File videoFile in fileList) {
      String name = getDefaultFileName(true);
      nameList.add(name);
      Future<VgHttpResponse> future = uploadVideo(videoFile, name);
      futureList.add(future);
    }
    try {
      Future.wait(futureList).then((values) {
        //values是个数组，分别是每一个任务返回的结果
        for (int i = 0; i < values.length; i++) {
          if (values[i].code == 200) {
            // 上传成功 oss不会返回图片地址 需要自己拼接
            String imgUrl =
                RESULT_URL + "/" + FOLDER_VIDEO + "/" + nameList[i];
            urlList.add(imgUrl);
            LogUtils.i(imgUrl);
          } else {
            callback?.onError(values[i]?.message);
            LogUtils.i(values[i]?.message);
            return;
          }
        }
        uploadBean.videoList = urlList;
        uploadBean.videoUrls = StringUtils.listToString(urlList);
        callback?.onSuccess(uploadBean);
      });
    } catch (e) {
      //错误处理
      LogUtils.e(e?.toString());
      callback?.onError("上传视频内容错误：" + e?.toString());
    }
  }

  /// 单独上传一个图片的方法
  static Future<VgHttpResponse> uploadImage(File imageFile, String fileName,
      {bool isNoCompress, ValueChanged<int> onGetNewFileLength}) async {
    Directory directory = await getTemporaryDirectory();
    String tempPath =
        directory.path + "/imageTemp" + getDefaultFileName(false);
    int startTime = DateTime
        .now()
        .millisecondsSinceEpoch;
    int length = await imageFile.length();
    String path = imageFile.path;
    // 按图片大小设置压缩质量
    int quality = 70;
    if (isNoCompress != null && isNoCompress == true) {
      quality = 100;
    }
    // else if(length > 5 * 1000 * 1000){
    //   quality = 50;
    // }
    // else if (length > 2 * 1000 * 1000) {
    //   quality = 20;
    // } else if (length > 1 * 1000 * 1000) {
    //   quality = 30;
    // } else if (length > 800 * 1000) {
    //   quality = 50;
    // } else if (length > 500 * 1000) {
    //   quality = 70;
    // } else {
    //   quality = 80;
    // }
    LogUtils.i("length：$length   quality：$quality");
    if(quality != 100){
      File result = await FlutterImageCompress.compressAndGetFile(
          imageFile.absolute.path, tempPath,
          quality: quality, format: CompressFormat.png);
      path = result.path;
      if(onGetNewFileLength != null){
        onGetNewFileLength.call(result.lengthSync());
      }
      LogUtils.i("压缩用时:${DateTime
          .now()
          .millisecondsSinceEpoch - startTime}");
    }else{
      if(onGetNewFileLength != null){
        onGetNewFileLength.call(length);
      }
    }
    //文件名
    FormData data = FormData.fromMap({
      'Filename': fileName,
      'key': FOLDER_IMG + "/" + fileName,
      'policy': _getPolicy(),
      'OSSAccessKeyId': ACCESSID,
      'success_action_status': '200', //让服务端返回200，不然，默认会返回204
      'signature': _getSignature(),
      'file': MultipartFile.fromFileSync(path, filename: fileName),
      'x-oss-content-type': 'image/png'
    });
    return HttpUtils.post(
        url: OSS_UPLOAD_API, body: data, contentType: "multipart/form-data");
  }

  /// 单独上传一个视频的方法
  static Future<VgHttpResponse> uploadVideo(File videoFile,
      String fileName) async {
    //文件名
    File realFile;
    if (Platform.isIOS) {
      // ios不压缩
      realFile = videoFile;
    } else {
      if (await videoFile.length() / 1000 / 1000 > 100) {
        LogUtils.i("视频压缩开始");
        //如果当前有正在压缩的，等待最多5分钟；
        VideoCompress();
        waitCompass(0);
        int startTime = DateTime
            .now()
            .millisecondsSinceEpoch;
        if (!VideoCompress.isCompressing) {
          MediaInfo info = await VideoCompress.compressVideo(
            videoFile.path,
            quality: VideoQuality.DefaultQuality,
            deleteOrigin: false,
          );
          LogUtils.i(
              "视频压缩用时:${DateTime
                  .now()
                  .millisecondsSinceEpoch - startTime}");
          LogUtils.i(
              "压缩前文件大小:${await videoFile.length() / 1000}--压缩后文件大小:${info
                  .filesize / 1000}");
          realFile = info.file;
        } else {
          realFile = videoFile;
        }
      } else {
        realFile = videoFile;
      }
    }
    FormData data = FormData.fromMap({
      'Filename': fileName,
      'key': FOLDER_VIDEO + "/" + fileName,
      'policy': _getPolicy(),
      'OSSAccessKeyId': ACCESSID,
      'success_action_status': '200', //让服务端返回200，不然，默认会返回204
      'signature': _getSignature(),
      'file': MultipartFile.fromFileSync(realFile.path, filename: fileName),
      'x-oss-content-type': 'video/mp4'
    });
    return HttpUtils.post(url: OSS_UPLOAD_API, body: data);
  }

  /// 获取上传签名（根据一系列转码得到）
  static String _getSignature() {
    //进行policyutf8编码
    List<int> policy = utf8.encode(_getPolicy());
    //进行utf8 编码
    List<int> key = utf8.encode(ACCESSKEY);
    //通过hmac,使用sha1进行加密
    List<int> signaturePre = Hmac(sha1, key)
        .convert(policy)
        .bytes;
    //最后一步，将上述所得进行base64 编码
    return base64.encode(signaturePre);
  }

  /// 获取oss上传所需的Post请求的policy
  static String _getPolicy() {
    //验证文本域 Post请求的policy表单域用于验证请求的合法性。Post policy中必须包含expiration和conditions policy为一段经过UTF-8和base64编码的JSON文本，声明了Post请求必须满足的条件。
    String policyText =
        '{"expiration": "2025-01-01T12:00:00.000Z","conditions": [{"bucket": "$BUCKET_NAME" }]}';
    //进行utf8编码
    List<int> policyTextUtf8 = utf8.encode(policyText);
    //进行base64编码
    return base64.encode(policyTextUtf8);
  }

  /// 获取默认的图片/视频名称 当前时间+随机数
  static String getDefaultFileName(bool isVideo, {String imageFormat}) {
    String format = "jpg";
    if(StringUtils.isNotEmpty(imageFormat)){
      format = imageFormat;
    }
    String scope = "0123456789";
    String result = "";
    // 为防止名称重复产生文件覆盖 这里拼接上随机数
    for (int i = 0; i < 4; i++) {
      result = result + scope[Random().nextInt(scope.length)];
    }
    //yyyyMMddhhmmss_xxxx
    String now =
    DateUtil.formatDate(DateTime.now(), format: DataFormats.full_2);
    return "$now$result.${isVideo ? 'mp4' : 'png'}";
  }

  ///带进度上传多个视频
  static Future<void> uploadMulVideoWithProgress(
      {List<File> files, List<String> paths, UploadCallback callback}) async {
    assert(files != null || paths != null,
    'files and paths cannot be empty at the same time');

    Directory directory = await getTemporaryDirectory();
    String coverFolderPath = directory.path + "/imageTemp";
    // 要上传的文件集合
    List<File> fileList = List<File>();

    if (files == null) {
      for (String path in paths) {
        fileList.add(File(path));
      }
    } else {
      fileList.addAll(files);
    }
    assert(fileList.length > 0, 'files cannot be empty');

    List<File> coverList = List<File>();

    for (File videoFile in fileList) {
      String coverPath = await VideoThumbnail.thumbnailFile(
        video: videoFile.path,
        thumbnailPath: coverFolderPath,
        imageFormat: ImageFormat.JPEG,
        maxWidth: 1920,
        quality: 100,
      );
      coverList.add(File(coverPath));
    }
    // 先上传封面再上传视频  封面传好进度0.1 视频上传结束1
    uploadMulImage(
        files: coverList,
        callback: BaseCallback(onSuccess: (val) {
          // 上传封面成功 开始上传视频 0.1
          callback.onProgress(0.1);
          upLoadVideoByQueueWithProgress(val, fileList,
              callback: UploadCallback(onSuccess: (val) {
                callback.onProgress(1);
                callback.onSuccess(val);
              }, onError: (msg) {
                callback.onError(msg);
              }, onProgress: (progress, {String msg}) {
                //上传视频成功 共1
                callback.onProgress(0.1 + 0.9 * progress, msg: msg);
              }));
        }, onError: (msg) {
          callback?.onError(msg);
        }));
  }

  /// 带进度的单独上传一个视频的方法
  /// 进度：压缩0-0.6 上传0.6-1
  static Future<VgHttpResponse> _uploadVideoWithProgress(File videoFile,
      String fileName, UploadCallback callback) async {
    //文件名
    File realFile;
    double compassDuration = 0.5;
    if (Platform.isIOS) {
      // ios不压缩
      realFile = videoFile;
      compassDuration = 0;
    } else {
      if (await videoFile.length() / 1000 / 1000 > 100) {
        //大于100M 压缩
        //如果当前有正在压缩的，等待最多5分钟；
        VideoCompress();
        waitCompass(0);
        if (!VideoCompress.isCompressing) {
          Subscription _subscription;
          callback.onProgress(0, msg: "正在压缩视频");
          if (VideoCompress.compressProgress$.notSubscribed) {
            compassDuration=0.6;
            _subscription =
                VideoCompress.compressProgress$.subscribe((double onData) {
                  LogUtils.i("视频压缩进度:${onData/100}");
                  callback.onProgress(onData * compassDuration/100);
                }, onDone: () {}, onError: (val) {}, cancelOnError: true);
          }

          int startTime = DateTime
              .now()
              .millisecondsSinceEpoch;
          MediaInfo info = await VideoCompress.compressVideo(
            videoFile.path,
            quality: VideoQuality.DefaultQuality,
            deleteOrigin: false,
          );
          LogUtils.i(
              "视频压缩用时:${DateTime
                  .now()
                  .millisecondsSinceEpoch - startTime}");
          LogUtils.i(
              "压缩前文件大小:${await videoFile.length() / 1000}--压缩后文件大小:${info
                  .filesize / 1000}");
          realFile = info.file;
          _subscription?.unsubscribe();
        } else {
          //当前有正在压缩的且等待了5分钟，直接上传
          realFile = videoFile;
          compassDuration = 0;
        }
      } else {
        realFile = videoFile;
        compassDuration = 0;
      }
    }
    if(realFile==null){
      return VgHttpResponse(code: 0);
    }
    callback.onProgress(0.2);
    //文件名
    FormData formData = FormData.fromMap({
      'Filename': fileName,
      'key': FOLDER_VIDEO + "/" + fileName,
      'policy': _getPolicy(),
      'OSSAccessKeyId': ACCESSID,
      'success_action_status': '200', //让服务端返回200，不然，默认会返回204
      'signature': _getSignature(),
      'file': MultipartFile.fromFileSync(realFile.path, filename: fileName),
      'x-oss-content-type': 'video/mp4'
    });
    Dio dio = new Dio();

    /// 上传单个文件
    Response res = await dio.post(
      OSS_UPLOAD_API,
      data: formData,
      onSendProgress: (count, total) {
        double progress = count / total;
        callback.onProgress(compassDuration + (1 - compassDuration) * progress);
      },
    );
    LogUtils.i("上传文件返回值${res.data}");
    return VgHttpResponse(
        code: res.statusCode, message: res.statusMessage, data: res.data);
  }

  ///带进度的上传视频
  static void upLoadVideoByQueueWithProgress(OssUploadBean uploadBean,
      List<File> fileList,
      {UploadCallback callback}) {
    // 预先设定好每个要上传的视频名字
    List<String> nameList = List<String>();

    // 已上传完的视频url集合
    List<String> urlList = List<String>();
    // 执行多个上传任务的future
    List<Future<VgHttpResponse>> futureList = List<Future<VgHttpResponse>>();
    Map<String, double> progressMap = HashMap();

    for (File videoFile in fileList) {
      String name = getDefaultFileName(true);
      nameList.add(name);
      Future<VgHttpResponse> future = _uploadVideoWithProgress(videoFile, name,
          UploadCallback(onProgress: (progress, {msg}) {
            progressMap[name] = progress;
            print("上传$name的进度:$progress");
            callback.onProgress(
                _getTotalProgress(progressMap, fileList.length), msg: msg);
          }, onError: callback?.onError));
      futureList.add(future);
    }
    try {
      Future.wait(futureList).then((values) {
        //values是个数组，分别是每一个任务返回的结果
        for (int i = 0; i < values.length; i++) {
          if (values[i].code == 200) {
            // 上传成功 oss不会返回图片地址 需要自己拼接
            String imgUrl =
                RESULT_URL + "/" + FOLDER_VIDEO + "/" + nameList[i];
            urlList.add(imgUrl);
            LogUtils.i(imgUrl);
          } else {
            callback?.onError(values[i]?.message);
            LogUtils.i(values[i]?.message);
            return;
          }
        }
        uploadBean.videoList = urlList;
        uploadBean.videoUrls = StringUtils.listToString(urlList);
        callback?.onSuccess(uploadBean);
      });
    } catch (e) {
      //错误处理
      LogUtils.e(e?.toString());
      callback?.onError("上传视频内容错误：" + e?.toString());
    }
  }

  ///多个进度累加
  static double _getTotalProgress(Map<String, double> progressMap, int length) {
    double progress = 0;
    if (progressMap != null && length > 0) {
      for (double d in progressMap.values) {
        progress += d;
      }
    }
    return progress;
  }

  ///等待压缩
  static void waitCompass(int count) {
    //最多等5分钟
    if (VideoCompress.isCompressing && count <= 3 * 5) {
      LogUtils.d("当前正在压缩，等待中...");
      Future.delayed(Duration(seconds: 20), () {
        count += 1;
        LogUtils.d("第$count次重试");
        waitCompass(count);
      });
    } else {
      if (count > 15) {
        LogUtils.d("等待超时，不等了");
      }
    }
  }


  /// 带进度的单独上传一个视频的方法
  static Future<VgHttpResponse> uploadVideoWithProgress(File videoFile,
      String fileName, UploadCallback callback) async {
    //文件名
    File realFile;
    int startTime = DateTime
        .now()
        .millisecondsSinceEpoch;
    double compassAllProgress = 0;
    if (Platform.isIOS) {
      // ios不压缩
      realFile = videoFile;
    } else {
      if (await videoFile.length() / 1000 / 1000 > 100) {
        //大于100M 压缩
        compassAllProgress = 0.5;
        callback.onProgress(0, msg: "正在压缩视频");
        //压缩视频的路径
        Directory directory = await getTemporaryDirectory();
        String compassPath = directory.path + "/imageTemp" + fileName;
        //开始压缩
        bool compassSuccess = await VideoCompassPlugin()
            .compassVideo(videoFile.path, compassPath, (progress) {
          callback.onProgress(progress / 100 * 0.5);
          print("压缩的进度:$progress / 100");
        });
        if (compassSuccess) {
          realFile = new File(compassPath);
          LogUtils.i(
              "视频压缩用时:${DateTime
                  .now()
                  .millisecondsSinceEpoch - startTime}");
        } else {
          LogUtils.i("视频压缩失败");
        }

        LogUtils.i("压缩前:${await videoFile.length() / 1000},压缩后：${await realFile
            .length() / 1000}");
      }
      if (realFile == null) {
        realFile = videoFile;
      }
    }

    try {
      //文件名
      FormData formData = FormData.fromMap({
        'Filename': fileName,
        'key': FOLDER_VIDEO + "/" + fileName,
        'policy': _getPolicy(),
        'OSSAccessKeyId': ACCESSID,
        'success_action_status': '200', //让服务端返回200，不然，默认会返回204
        'signature': _getSignature(),
        'file': MultipartFile.fromFileSync(realFile.path, filename: fileName),
        'x-oss-content-type': 'video/mp4'
      });
      Dio dio = new Dio();

      /// 上传单个文件
      Response res = await dio.post(
        OSS_UPLOAD_API,
        data: formData,
        onSendProgress: (count, total) {
          double progress = count / total;

          callback.onProgress(compassAllProgress + 0.5 * progress);
        },
      );
      String imgUrl =
          RESULT_URL + "/" + FOLDER_VIDEO + "/" + fileName;
      LogUtils.i("上传文件返回值$imgUrl");
      LogUtils.i(
          "上传视频用时:${DateTime
              .now()
              .millisecondsSinceEpoch - startTime}");
      return VgHttpResponse(
          code: res.statusCode, message: res.statusMessage, data: res.data);
    } catch (e) {
      return VgHttpResponse(
          code: 0, message: "视频上传请求失败", data: e?.toString());
    }
  }


  /// 带进度的单独上传一个视频的方法
  static Future<VgHttpResponse> uploadVideoWithProgressTest(File videoFile,
      String fileName, int quality, UploadCallback callback) async {
    //文件名
    File realFile;
    int startTime = DateTime
        .now()
        .millisecondsSinceEpoch;
    double compassAllProgress = 0;
    if (Platform.isIOS) {
      // ios不压缩
      realFile = videoFile;
    } else {
      if (await videoFile.length() / 1000 / 1000 > 100) {
        //大于100M 压缩
        compassAllProgress = 0.5;
        callback.onProgress(0, msg: "正在压缩视频");
        //压缩视频的路径
        Directory directory = await getTemporaryDirectory();
        String compassPath = directory.path + "/imageTemp" + fileName;
        //开始压缩
        bool compassSuccess = await VideoCompassPlugin()
            .compassVideoTest(videoFile.path, compassPath, quality, (progress) {
          callback.onProgress(progress / 100 * 0.5);
          print("压缩的进度:$progress / 100");
        });
        if (compassSuccess) {
          realFile = new File(compassPath);
          LogUtils.i(
              "视频压缩用时:${DateTime
                  .now()
                  .millisecondsSinceEpoch - startTime}");
        } else {
          LogUtils.i("视频压缩失败");
        }

        LogUtils.i("压缩前:${await videoFile.length() / 1000},压缩后：${await realFile
            .length() / 1000}");
        callback.onSuccess(videoFile.path);
        return null;
      }
      if (realFile == null) {
        realFile = videoFile;
      }
    }

    try {
      //文件名
      FormData formData = FormData.fromMap({
        'Filename': fileName,
        'key': FOLDER_VIDEO + "/" + fileName,
        'policy': _getPolicy(),
        'OSSAccessKeyId': ACCESSID,
        'success_action_status': '200', //让服务端返回200，不然，默认会返回204
        'signature': _getSignature(),
        'file': MultipartFile.fromFileSync(realFile.path, filename: fileName),
        'x-oss-content-type': 'video/mp4'
      });
      Dio dio = new Dio();

      /// 上传单个文件
      Response res = await dio.post(
        OSS_UPLOAD_API,
        data: formData,
        onSendProgress: (count, total) {
          double progress = count / total;

          callback.onProgress(compassAllProgress + 0.5 * progress);
        },
      );
      // 上传成功 oss不会返回图片地址 需要自己拼接
      String imgUrl =
          RESULT_URL + "/" + FOLDER_VIDEO + "/" + fileName;
      LogUtils.i("上传文件返回值$imgUrl");
      LogUtils.i(
          "上传视频用时:${DateTime
              .now()
              .millisecondsSinceEpoch - startTime}");
      return VgHttpResponse(
          code: res.statusCode, message: res.statusMessage, data: res.data);
    } catch (e) {
      return VgHttpResponse(
          code: 0, message: "视频上传请求失败", data: e?.toString());
    }
  }

  ///取消压缩
  static cancelCompression(){
    VideoCompress.cancelCompression();
  }

  ///删除oss文件
  static Future<VgHttpResponse> deleteObject(String fileUrl,
      {BaseCallback callback}) async {
    if (StringUtils.isEmpty(fileUrl)) {
      callback?.onError("文件为空");
      return null;
    }
    ///获取尾缀值
    String fileUrlSuffix = fileUrl.replaceAll(RESULT_URL+"/", "").replaceAll(RESULT_URL_HTTP+"/", "");
    var result = Dio();
    // // 增加log拦截器，用于打印请求的log
    // result.interceptors.add(InterceptorsWrapper(onRequest: (req) {
    //   var method = req.method;
    //   var uri = req.uri;
    //   var headers = req.headers;
    //   var body = req.data;
    //   LogUtils.d('-> $method $uri');
    //   LogUtils.d('headers:');
    //   headers.forEach((key, val) {
    //     LogUtils.d('$key:$val');
    //   });
    //   LogUtils.d('body:');
    //   LogUtils.d('$body');
    //   LogUtils.d('<-- END HTTP REQUESE');
    //   return req;
    // }, onResponse: (resp) {
    //   var code = resp.statusCode;
    //   var uri = resp.request.uri.toString();
    //   var headers = resp.headers;
    //   var body = resp.data;
    //   LogUtils.d('<- $code $uri');
    //   LogUtils.d('headers:');
    //   headers.forEach((key, val) {
    //     LogUtils.d('$key:$val');
    //   });
    //   LogUtils.d('body:');
    //   LogUtils.d('$body');
    //   LogUtils.d('<-- END HTTP RESPONSE');
    //   return resp;
    // }, onError: (err) {
    //   var req = err.request;
    //   var method = req.method;
    //   var uri = req.uri;
    //   LogUtils.d('<- $method  $uri has failed ${err.message}');
    //   LogUtils.d('<-- END HTTP ERROR');
    //   return err;
    // }));
    Response res = await result.delete(OSS_UPLOAD_API + "/" + "$fileUrlSuffix",
        options: Options(headers: {
          'Authorization': _getDeleteAuthorization(fileUrlSuffix),
          "Date": getGMTNow()
        }));
    if(res.statusCode == 204){
      callback?.onSuccess("删除阿里云资源成功");
      print("删除的资源路径：$fileUrl");
    }else{
      callback?.onError("删除阿里云资源失败：${res?.statusMessage}");
    }
    return VgHttpResponse(
        code: res.statusCode, message: res.statusMessage, data: res.data);
  }

  static String _getDeleteAuthorization(String fileUrl) {
    //拼密钥
    String policyStr = "DELETE" + "\n"
        + "" + "\n"
        + "" + "\n"
        + getGMTNow() + "\n"
        // + CanonicalizedOSSHeaders
        + ""
        + "/$BUCKET_NAME/" + "$fileUrl";
    //进行policyutf8编码
    List<int> policy = utf8.encode(policyStr);
    //进行utf8 编码
    List<int> key = utf8.encode(ACCESSKEY);
    //通过hmac,使用sha1进行加密
    List<int> signaturePre = Hmac(sha1, key)
        .convert(policy)
        .bytes;
    //最后一步，将上述所得进行base64 编码
    String signature = base64.encode(signaturePre);

    String authorization = "OSS " + ACCESSID + ":" + signature;
    return authorization;
  }

  static String getGMTNow() {
    Map<int, String> weekMap = {
      7: 'Sun', 1: 'Mon', 2: 'Tue', 3: 'Wed', 4: 'Thu', 5: 'Fri', 6: 'Sat'
    };
    Map<int, String> monthMap = {
      1: 'Jan',
      2: 'Feb',
      3: 'Mar',
      4: 'Apr',
      5: 'May',
      6: 'Jun',
      7: 'Jul',
      8: 'Aug',
      9: 'Sep',
      10: 'Oct',
      11: 'Nov',
      12: 'Dec'
    };
    var dateTime = DateTime.now().subtract(Duration(hours: 8));
    String gmt = weekMap[dateTime?.weekday] + ", " + "${dateTime?.day}" + " " +
        monthMap[dateTime?.month] + " " + _getFormatDate(dateTime?.year) + " " +
        "${_getFormatDate(dateTime?.hour)}:${_getFormatDate(dateTime?.minute)}:${_getFormatDate(dateTime?.second)}" + " " +
        "GMT";
    print(gmt);
    return gmt;
  }

  static String _getFormatDate(int value){
    if(value == null){
      return "00";
    }
    if(value < 10){
      return "0$value";
    }
    return value?.toString();
  }
}
